/*
    Copyright 2011 - Tommi Laukkanen (www.substanceofcode.com)

    This file is part of NewsFlow.

    NewsFlow is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    NewsFlow is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with NewsFlow. If not, see <http://www.gnu.org/licenses/>.
*/

var sid = "";
var sidToken = "";

// UI components
var waiting;
var done;
var model;
var tagsModel;
var logo;
var error;
var navigation;

var continuation = "";
var actionID = "";
var actionFeedUrl = "";
var accessToken = "";
var action = "";
var tags = "";

var itemsURL = "";

function setComponents(nav, wait, mod, tags, log, doneIndicator, errorIndicator) {
    navigation = nav;
    waiting = wait;
    model = mod;
    tagsModel = tags;
    logo = log;
    done = doneIndicator;
    error = errorIndicator;
}

function doWebRequest(method, url, params, callback) {
    var doc = new XMLHttpRequest();
    //console.log(method + " " + url);

    doc.onreadystatechange = function() {
        if (doc.readyState == XMLHttpRequest.HEADERS_RECEIVED) {
            var status = doc.status;
            if(status!=200) {
                showError("Google API returned " + status + " " + doc.statusText);
            }
        } else if (doc.readyState == XMLHttpRequest.DONE) {
            var data;
            var contentType = doc.getResponseHeader("Content-Type");
            data = doc.responseText;
            callback(data);
        }
    }

    doc.open(method, url);
    if(sid.length>0) {
        //console.log("Authorization GoogleLogin auth=" + sid);
        doc.setRequestHeader("Authorization", "GoogleLogin auth=" + sid);
        doc.setRequestHeader("Cookie", "SID=" + sidToken);
    }
    if(params.length>0) {
        //console.log("Sending: " + params);
        doc.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
        doc.setRequestHeader("Content-Length", String(params.length));
        doc.send(params);
    } else {
        doc.send();
    }
}

/** Parse parameter from given URL */
function parseAuth(data, parameterName) {
    var parameterIndex = data.indexOf(parameterName + "=");
    if(parameterIndex<0) {
        // We didn't find parameter
        console.log("Didn't find Auth");
        addError("Didn't find Auth");
        return "";
    }
    var equalIndex = data.indexOf("=", parameterIndex);
    if(equalIndex<0) {
        return "";
    }

    var lineBreakIndex = data.indexOf("\n", equalIndex+1)

    var value = "";
    value = data.substring(equalIndex+1, lineBreakIndex);
    return value;
}

function addError(msg) {
    model.append({
                 "title": "Error",
                 "desc": msg,
                 "author": "",
                 "published": "",
                 "more": true,
                 "source": ""});}

function login(email, password, model) {
    try {
        waiting.state = "shown";
        var url = "https://www.google.com/accounts/ClientLogin?Email=" + encodeURIComponent(email) + "&Passwd=" + encodeURIComponent(password) + "&service=reader";
        doWebRequest("GET", url, "", parseToken);
    }catch(err) {
        showError("Error while logging in.");
    }
}

function showError(msg) {
    waiting.state = "hidden";
    error.reason = msg;
    error.state = "shown";
}

function removeLinks(original) {
    var txt = original;
    txt = txt.replace(/<a /g, "<span ");
    txt = txt.replace(/<\/a>/g, "</span>");
    return txt;
}

function parseToken(data) {
    sid = parseAuth(data, "Auth");
    //console.log("Auth=" + sid);
    sidToken = parseAuth(data, "SID");
    //console.log("SID=" + sidToken);
    logo.state = "hidden"; //.visible = false;
    if(sid.length>0) {
        navigation.state = "menu";
        waiting.state = "hidden";
        //loadUnreadNews();
    } else {
        addError("Couldn't parse SID");
        waiting.state = "hidden";
    }
}

function loadSubscriptions() {
    waiting.state = "shown";
    var url = "http://www.google.com/reader/api/0/subscription/list?output=json";
    doWebRequest("GET", url, "", parseSubscriptions);
}

function parseSubscriptions(data) {
    //console.log("Subscriptions: " + data);
    tagsModel.clear();
    var tags = eval("[" + data + "]")[0];
    for(var i in tags.subscriptions) {
        var tag = tags.subscriptions[i];
        var id = tag.id;
        var title = tag.title;
        tagsModel.append({"title": title, "id":id});
    }
    navigation.state = "tags";
    waiting.state = "hidden";
}

function loadTags() {
    waiting.state = "shown";
    var url = "http://www.google.com/reader/api/0/tag/list?output=json";
    doWebRequest("GET", url, "", parseTags);
}

function parseTags(data) {
    tagsModel.clear();
    var tags = eval("[" + data + "]")[0];
    for(var i in tags.tags) {
        var tag = tags.tags[i];
        var id = tag.id;
        var title = id;
        while(title.indexOf("/")>0) {
            var index = title.indexOf("/");
            title = title.substring(index+1);
        }
        tagsModel.append({"title": title, "id":id});
    }
    navigation.state = "tags";
    waiting.state = "hidden";
}

function loadAllNews() {
    itemsURL = "http://www.google.com/reader/api/0/stream/contents/user/-/state/com.google/reading-list";
    loadNews();
}

function loadUnreadNews() {
    itemsURL = "http://www.google.com/reader/api/0/stream/contents/user/-/state/com.google/reading-list?xt=user/-/state/com.google/read";
    loadNews();
}

function loadStarred() {
    itemsURL = "http://www.google.com/reader/api/0/stream/contents/user/-/state/com.google/starred";
    loadNews();
}

function loadTaggedItems(tag) {
    itemsURL = "http://www.google.com/reader/api/0/stream/contents/" + tag;
    loadNews();
}

function loadSubscriptionItems(subscription) {
    itemsURL = "http://www.google.com/reader/api/0/stream/contents/" + subscription;
    loadNews();
}

function loadNews() {
    try {
        model.clear();
        waiting.state = "shown";
        doWebRequest("GET", itemsURL, "", parseNews);
    } catch(err) {
        showError("Error while loading news: " + err);
    }
}

function getNodeValue(node, name) {
    var nodeValue = "";
    for(var i=0; i<node.childNodes.length; i++) {
        var nodeName = node.childNodes[i].nodeName;
        if(nodeName==name) {
            nodeValue = node.childNodes[i].firstChild.nodeValue;
        }
    }
    return nodeValue;
}

function parseEntry(item) {
    var content = ""
    if(typeof(item.content)!=undefined && item.content!=null) {
        content = item.content.content;
    } else if(typeof(item.summary)!=undefined && item.summary!=null) {
        content = item.summary.content;
    } else {
        content = "";
    }
    content = removeLinks(content);
    var milliseconds = parseInt(parseInt(item.published)*1000);
    var published = new Date(parseInt(milliseconds));
    var link = item.alternate[0].href;
    //console.log("Link: " + link);
    var isRead = true;
    for(var i in item.categories) {
        var category = item.categories[i];
        if(category.indexOf("/reading-list")>0) {
            isRead = false;
        }
    }


    model.append({
                 "id": item.id,
                 "title": item.title,
                 "desc": content,
                 "author": item.origin.title,
                 "published": prettyDate(published),
                 "more": false,
                 "source": item.origin.title,
                 "link": link,
                 "feedUrl": item.origin.streamId,
                 "isRead": isRead
    });
}

function parseNews(data) {
    //try {
        //console.log("DATA: " + data);
        var doc = eval("[" + data + "]")[0];
        if(doc==null || typeof(doc)==undefined) {
            model.append({
                         "title": "Error",
                         "desc": "",
                         "author": "",
                         "published": "",
                         "more": true,
                         "isRead": false,
                         "source": ""});
            waiting.state = "hidden";
            return;
        }

        var moreIndex = model.count - 1;

        continuation = doc.continuation;
        for(var i in doc.items) {
            var item = doc.items[i];
            parseEntry(item);
        }

        if(moreIndex>0) {
            if(model.get(moreIndex).title.indexOf("Loading...")>-1) {
                model.remove(moreIndex);
            }
        }

        model.append({
                     "title": "Load more...<br/><br/>",
                     "desc": "",
                     "author": "",
                     "published": "",
                     "isRead": false,
                     "more": true,
                     "source": ""});
    //}catch(err) {
    //    addError("Error: " + err);
    //}
    navigation.state = "items";
    waiting.state = "hidden";
}

function loadMore() {
    waiting.state = "shown";
    var url = itemsURL;
    if(itemsURL.indexOf("?")>0) {
        url += "&";
    } else {
        url += "?";
    }
    url += "c=" + continuation;
    doWebRequest("GET", url, "", parseNews);
}

function getToken() {
    var url = "http://www.google.com/reader/api/0/token";
    doWebRequest("GET", url, "", parseAccessToken);
}

function parseAccessToken(data) {
    accessToken = data;
    if(action=="read") {
        var url = "http://www.google.com/reader/api/0/edit-tag";
        var dd = "ac=edit-tags&a=user/-/state/com.google/read&i=" + encodeURIComponent(actionID) + "&s=" + encodeURIComponent(actionFeedUrl) + "&T=" + accessToken;
        doWebRequest("POST", url, dd, showDone);
    } else if(action=="unread") {
        var url = "http://www.google.com/reader/api/0/edit-tag";
        var dd = "ac=edit-tags&a=user/-/state/com.google/kept-unread&r=user/-/state/com.google/read&i=" + encodeURIComponent(actionID) + "&s=" + encodeURIComponent(actionFeedUrl) + "&T=" + accessToken;
        doWebRequest("POST", url, dd, showDone);
    } else if(action=="fav") {
        var url = "http://www.google.com/reader/api/0/edit-tag?client=-";
        var dd = "a=user/-/state/com.google/starred&i=" + encodeURIComponent(actionID) + "&s=" + encodeURIComponent(actionFeedUrl) + "&T=" + accessToken;
        doWebRequest("POST", url, dd, showDone);
    } else if(action=="tags") {
        var url = "http://www.google.com/reader/api/0/edit-tag?client=-";
        var dd =
            "a=user/-/label/" + encodeURIComponent(tags) +
            "&i=" + encodeURIComponent(actionID) +
            "&s=" + encodeURIComponent(actionFeedUrl) +
            "&T=" + accessToken;
        doWebRequest("POST", url, dd, showDone);
    }
}

function markAsRead(id, feedUrl, showLoadingIndicator) {
    actionID = id;
    actionFeedUrl = feedUrl;
    if(showLoadingIndicator) {
        waiting.state = "shown";
    }
    action = "read";
    getToken();
}

function markAsUnread(id, feedUrl) {
    actionID = id;
    actionFeedUrl = feedUrl;
    waiting.state = "shown";
    action = "unread";
    done.status = "Marked as unread";
    getToken();
}

function addTags(id, feedUrl, newTags) {
    actionID = id;
    actionFeedUrl = feedUrl;
    waiting.state = "shown";
    action = "tags";
    done.status = "Added tags";
    tags = newTags;
    getToken();
}

function markAsFavourite(id, feedUrl) {
    actionID = id;
    actionFeedUrl = feedUrl;
    waiting.state = "shown";
    action = "fav";
    done.status = "Marked as favourite";
    getToken();
}

function showDone(data) {
    console.log("DONE: " + data);
    if(waiting.state!="shown") {
        return;
    }
    waiting.state = "hidden";
    done.status = "";
    if(typeof(data)!=undefined && data!=null) {
        if(action=="read") {
            done.status = "Marked as read " + data;
        } else if(action=="unread") {
            done.status = "Marked as unread " + data;
        } else {
            done.status = "" + data;
        }
    }
    done.state = "shown";
}

function doNothing(data) {
    // Nothing...
}

function prettyDate(date){
    try {
        var diff = (((new Date()).getTime() - date.getTime()) / 1000);
        var day_diff = Math.floor(diff / 86400);

        if ( isNaN(day_diff) || day_diff >= 31 ) {
            //console.log("Days: " + day_diff);
            return "some time ago";
        } else if (day_diff < 0) {
            //console.log("day_diff: " + day_diff);
            return "just now";
        }

        return day_diff == 0 && (
                    diff < 60 && "just now" ||
                    diff < 120 && "1 minute ago" ||
                    diff < 3600 && Math.floor( diff / 60 ) + " min ago" ||
                    diff < 7200 && "1 hour ago" ||
                    diff < 86400 && Math.floor( diff / 3600 ) + " hours ago") ||
                day_diff == 1 && "Yesterday" ||
                day_diff < 7 && day_diff + " days ago" ||
                day_diff < 31 && Math.ceil( day_diff / 7 ) + " weeks ago";
        day_diff >= 31 && Math.ceil( day_diff / 30 ) + " months ago";
    } catch(err) {
        console.log("Error: " + err);
        return "some time ago";
    }
}

// 2011-01-24T18:48:00Z
function parseDate(stamp)
{
    try {
        //console.log("stamp: " + stamp);
        var parts = stamp.split("T");
        var day;
        var time;
        var hours;
        var minutes;
        var seconds = 0;
        var year;
        var month;

        var dates = parts[0].split("-");
        year = parseInt(dates[0]);
        month = parseInt(dates[1])-1;
        day = parseInt(dates[2]);

        var times = parts[1].split(":");
        hours = parseInt(times[0]);
        minutes = parseInt(times[1]);

        var dt = new Date();
        dt.setUTCDate(day);
        dt.setYear(year);
        dt.setUTCMonth(month);
        dt.setUTCHours(hours);
        dt.setUTCMinutes(minutes);
        dt.setUTCSeconds(seconds);

        //console.log("day: " + day + " year: " + year + " month " + month + " hour " + hours);

        return dt;
    } catch(err) {
        console.log("Error while parsing date: " + err);
        return new Date();
    }
}
